package com.kzy.demoadmin.web.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.kzy.demoadmin.web.entity.User;
import com.kzy.demoadmin.web.service.UserService;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * JWT工具类
 * 调用该类的静态方法直接使用
 */
@Slf4j
@Component
public class JwtTokenUtils {

    private static UserService staticUserService;

//    静态方法调用需求：getCurrentUser() 是静态方法，
//    而 Spring 注入的 userService 是实例成员变量。
//    静态方法无法直接访问非静态成员变量，因此需要通过 @PostConstruct 在对象初始化时将实例变量赋值给静态变量 staticUserService。
    @Resource
    private UserService userService;

    //Spring 容器管理的是实例对象，无法直接注入静态变量。通过实例变量接收注入，再赋值给静态变量是一种常见的解决方案。
    @PostConstruct// 在类初始化时将userService设置给staticUserService
    public void setUserService() {
        staticUserService = userService;
    }

    /**
     * 生成token并返回给客户端
     * @param adminId 管理员id
     * @param password 密码
     * @return
     */
    public static String genToken(String adminId, String password) {
        return JWT.create().withAudience(adminId) // 将 user id 保存到 token 里面，作为载荷
                .withExpiresAt(DateUtil.offsetHour(new Date(), 24)) // 24小时后token过期
                .sign(Algorithm.HMAC256(password)); // 以 password 作为 token 的密钥
    }

    /**
     * 获取当前登录的用户信息
     */
    public static User getCurrentUser() {
        String token = null;
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest(); // 再获取请求,下面这个获取不到请求头的内容，需要用jakarta包里的HttpServletRequest
//            HttpServletRequest request = (HttpServletRequest) ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            token = request.getHeader("token");
            if (StrUtil.isBlank(token)) {
                token = request.getParameter("token");
            }
            if (StrUtil.isBlank(token)) {
                log.error("获取当前登录的token失败，token: {}", token);
                return null;
            }
            // 解析token，获取用户的id
            String adminId = JWT.decode(token).getAudience().get(0);
            return staticUserService.findById(Integer.valueOf(adminId));
        } catch (Exception e) {
            log.error("获取当前登录的管理员信息失败，token:{}", token, e);
            return null;
        }
    }


}